﻿using System;

using Microsoft.SqlServer.Dts.Pipeline;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
using System.Collections;

namespace MyDataGenerator2012
{
     [DtsPipelineComponent(
        DisplayName = "MyDataGenerator",
        ComponentType = ComponentType.SourceAdapter
     )]
    public class MyDataGenerator : PipelineComponent
    {
        #region Members
        ArrayList columnInformation;
        private bool Cancel;
        private Random rnd = new Random(DateTime.Now.Millisecond);
        private struct ColumnInfo
        {
            public int BufferColumnIndex;
            public string ColumnName;
            public DataType datatype;
            public int length { get; set; }
        }
        #endregion

        #region Design Time
        #region ProvideComponentProperties
        public override void ProvideComponentProperties()
        {
            // Support resetting the component.
            ComponentMetaData.RuntimeConnectionCollection.RemoveAll();
            RemoveAllInputsOutputsAndCustomProperties();

            // Add the Row count custom property
            IDTSCustomProperty100 rowcount = ComponentMetaData.CustomPropertyCollection.New();
            rowcount.Name = "RowCount";

            IDTSOutput100 output = ComponentMetaData.OutputCollection.New();
            output.Name = "Output";
            output.ExternalMetadataColumnCollection.IsUsed = false;

        }
        #endregion

        #region Validate
        /// <summary>
        /// Validate the component by checking the inputs, outputs, custom properties, and column metadata.
        /// </summary>
        /// <returns>A value from the DTSValidationStatus indicating the result of validation.</returns>
        public override DTSValidationStatus Validate()
        {
            IDTSOutput100 output = ComponentMetaData.OutputCollection[0];

            // check for the rowcount custom property
            IDTSCustomProperty100 rowcount = ComponentMetaData.CustomPropertyCollection["RowCount"];
            if (rowcount.Value == null || ((string)rowcount.Value).Length == 0)
            {
                ComponentMetaData.FireError(0, ComponentMetaData.Name, "rowcount property not specified.", "", 0, out this.Cancel);
                return DTSValidationStatus.VS_ISBROKEN;
            }

            if (ComponentMetaData.OutputCollection[0].OutputColumnCollection.Count == 0)
            {
                return DTSValidationStatus.VS_NEEDSNEWMETADATA;
            }

            // Return base class validation result.
            return base.Validate();
        }
        #endregion

        #region SetOutputColumnDataTypeProperties
        public override void SetOutputColumnDataTypeProperties(int iOutputID, int iOutputColumnID, DataType eDataType, int iLength, int iPrecision, int iScale, int iCodePage)
        {
            IDTSOutputColumn100 col = ComponentMetaData.OutputCollection.GetObjectByID(iOutputID).OutputColumnCollection.GetObjectByID(iOutputColumnID);
            col.SetDataTypeProperties(eDataType, iLength, iPrecision, iScale, iCodePage);
        }

        #endregion

        #endregion

        #region Run Time

        public override void PreExecute()
        {
            this.columnInformation = new ArrayList();
            IDTSOutput100 output = ComponentMetaData.OutputCollection[0];

            foreach (IDTSOutputColumn100 col in output.OutputColumnCollection)
            {
                ColumnInfo ci = new ColumnInfo();
                ci.BufferColumnIndex = BufferManager.FindColumnByLineageID(output.Buffer, col.LineageID);
                ci.ColumnName = col.Name;
                ci.datatype = col.DataType;
                ci.length = col.Length;
                columnInformation.Add(ci);
            }
        }

        public override void PrimeOutput(int outputs, int[] outputIDs, PipelineBuffer[] buffers)
        {
            IDTSOutput100 output = ComponentMetaData.OutputCollection[0];
            PipelineBuffer buffer = buffers[0];

            IDTSCustomProperty100 rowcount = ComponentMetaData.CustomPropertyCollection["RowCount"];

            int rc = int.Parse(rowcount.Value.ToString());

            for (int i = 0; i < rc; i++)
            {
                // Add a row to the output buffer.
                buffer.AddRow();
                for (int x = 0; x < columnInformation.Count; x++)
                {
                    ColumnInfo ci = (ColumnInfo)columnInformation[x];
                    try
                    {
                        buffer[ci.BufferColumnIndex] = GetNextValue(ci);
                    }
                    catch
                    {
                        buffer.SetNull(ci.BufferColumnIndex);
                    }
                }
            }

            buffer.SetEndOfRowset();
        }

        private object GetNextValue(ColumnInfo ci)
        {
            object val = null;
            switch (ci.datatype)
            {
                // The length cannot be zero, and the code page property must contain a valid code page.
                case DataType.DT_BOOL:
                    val = rnd.Next(1, 3) > 1 ? true : false;
                    break;
                case DataType.DT_GUID:
                    val = Guid.NewGuid();
                    break;
                case DataType.DT_STR:
                case DataType.DT_TEXT:
                case DataType.DT_WSTR:
                case DataType.DT_NTEXT:
                    if (ci.length.Equals(1))
                        val = rnd.Next(1, 3) > 1 ? "A" : "B";
                    else if (ci.length > 1 && ci.length < 9)
                        val = (char)('A' + rnd.Next(26)) + rnd.Next(1, (int)Math.Pow(10, ci.length - 1)).ToString();
                    else
                        val = (char)('A' + rnd.Next(26)) + rnd.Next(1, (int)Math.Pow(10, 9)).ToString();
                    val = rnd.Next(1, 101) < 6 && ci.length > 6 ? "Unknown" : val;
                    break;
                case DataType.DT_I1:
                    val = rnd.Next(1, 101);
                    break;
                case DataType.DT_NUMERIC:
                case DataType.DT_DECIMAL:
                case DataType.DT_I2:
                case DataType.DT_I4:
                case DataType.DT_I8:
                    val = rnd.Next(1, 65535);
                    break;
                case DataType.DT_DATE:
                case DataType.DT_DBDATE:
                case DataType.DT_DBTIME2:
                case DataType.DT_DBTIMESTAMP:
                case DataType.DT_DBTIMESTAMP2:
                case DataType.DT_DBTIMESTAMPOFFSET:
                    val = DateTime.Now.AddDays(-rnd.Next(1, 1095));
                    break;
                default:
                    break;

            }
            return val;
        }

        #endregion

    }
}
